#include "../../include/gudb.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void print_separator(const char* title) {
    printf("\n=== %s ===\n", title);
}

void show_tables_in_database(gudb_txn* txn, const char* db_name) {
    result_t* result = NULL;
    printf("Tables in %s:\n", db_name);
    if (gudb_exec(txn, "SHOW TABLES", NULL, &result) == GU_OK) {
        if (result->row_count == 0) {
            printf("  (no tables)\n");
        } else {
            for (uint32_t i = 0; i < result->row_count; i++) {
                printf("  - %s\n", result->rows[i][0]);
            }
        }
        gudb_free_result(result);
    } else {
        printf("  ERROR: Failed to show tables\n");
    }
}

int main() {
    printf("=== FINAL DATABASE ISOLATION TEST ===\n");
    
    // Clean start
    system("rm -rf ./final_test_db");
    
    // Open database
    gudb* db = gudb_open("./final_test_db", GU_OPEN_CREATE, "admin", "admin");
    if (!db) {
        printf("FAIL: Cannot open database\n");
        return 1;
    }
    
    // Begin transaction with default database
    gudb_txn* txn = gudb_begin(db, GU_TXN_RC, "gudb");
    if (!txn) {
        printf("FAIL: Cannot begin transaction\n");
        gudb_close(db);
        return 1;
    }
    
    result_t* result = NULL;
    
    print_separator("Step 1: Clean Environment");
    // Clean up any existing databases
    gudb_exec(txn, "DROP DATABASE IF EXISTS company", NULL, &result);
    if (result) gudb_free_result(result);
    gudb_exec(txn, "DROP DATABASE IF EXISTS school", NULL, &result);
    if (result) gudb_free_result(result);
    
    // Create test databases
    gudb_exec(txn, "CREATE DATABASE company", NULL, &result);
    if (result) gudb_free_result(result);
    gudb_exec(txn, "CREATE DATABASE school", NULL, &result);
    if (result) gudb_free_result(result);
    
    printf("Created databases: company, school\n");
    
    print_separator("Step 2: Test Company Database");
    // Switch to company database
    if (gudb_exec(txn, "USE company", NULL, &result) != GU_OK) {
        printf("FAIL: Cannot switch to company database\n");
        goto cleanup;
    }
    if (result) gudb_free_result(result);
    printf("Switched to company database\n");
    
    // Show tables (should be empty)
    show_tables_in_database(txn, "company");
    
    // Create tables in company database
    gudb_exec(txn, "CREATE TABLE employees (id INT, name VARCHAR(50), salary FLOAT)", NULL, &result);
    if (result) gudb_free_result(result);
    gudb_exec(txn, "CREATE TABLE departments (id INT, name VARCHAR(50))", NULL, &result);
    if (result) gudb_free_result(result);
    printf("Created tables: employees, departments\n");
    
    // Show tables in company
    show_tables_in_database(txn, "company");
    
    print_separator("Step 3: Test School Database");
    // Switch to school database
    if (gudb_exec(txn, "USE school", NULL, &result) != GU_OK) {
        printf("FAIL: Cannot switch to school database\n");
        goto cleanup;
    }
    if (result) gudb_free_result(result);
    printf("Switched to school database\n");
    
    // Show tables (should be empty - isolation test!)
    show_tables_in_database(txn, "school");
    
    // Create tables in school database
    gudb_exec(txn, "CREATE TABLE students (id INT, name VARCHAR(50), grade INT)", NULL, &result);
    if (result) gudb_free_result(result);
    gudb_exec(txn, "CREATE TABLE courses (id INT, name VARCHAR(50), credits INT)", NULL, &result);
    if (result) gudb_free_result(result);
    printf("Created tables: students, courses\n");
    
    // Show tables in school
    show_tables_in_database(txn, "school");
    
    print_separator("Step 4: Verify Company Database Isolation");
    // Switch back to company
    if (gudb_exec(txn, "USE company", NULL, &result) != GU_OK) {
        printf("FAIL: Cannot switch back to company database\n");
        goto cleanup;
    }
    if (result) gudb_free_result(result);
    printf("Switched back to company database\n");
    
    // Should only see company tables
    show_tables_in_database(txn, "company");
    
    print_separator("Step 5: Cross-Database Access Test");
    printf("Currently in company database, trying to access school tables...\n");
    
    // Try to access students table (should fail)
    printf("Trying to DROP TABLE students (from school):\n");
    if (gudb_exec(txn, "DROP TABLE students", NULL, &result) == GU_OK) {
        printf("  ERROR: Successfully dropped students table - isolation broken!\n");
        if (result) gudb_free_result(result);
    } else {
        printf("  GOOD: Failed to drop students table (table not found in current database)\n");
    }
    
    // Try to access courses table (should fail)
    printf("Trying to DROP TABLE courses (from school):\n");
    if (gudb_exec(txn, "DROP TABLE courses", NULL, &result) == GU_OK) {
        printf("  ERROR: Successfully dropped courses table - isolation broken!\n");
        if (result) gudb_free_result(result);
    } else {
        printf("  GOOD: Failed to drop courses table (table not found in current database)\n");
    }
    
    print_separator("Step 6: Verify School Database Still Intact");
    // Switch back to school
    if (gudb_exec(txn, "USE school", NULL, &result) != GU_OK) {
        printf("FAIL: Cannot switch back to school database\n");
        goto cleanup;
    }
    if (result) gudb_free_result(result);
    printf("Switched back to school database\n");
    
    // Should still see school tables
    show_tables_in_database(txn, "school");
    
    print_separator("Step 7: Insert and Query Test");
    // Insert data in school
    gudb_exec(txn, "INSERT INTO students VALUES (1, 'Alice', 95)", NULL, &result);
    if (result) gudb_free_result(result);
    gudb_exec(txn, "INSERT INTO courses VALUES (1, 'Math', 3)", NULL, &result);
    if (result) gudb_free_result(result);
    printf("Inserted data into school tables\n");
    
    // Switch to company and insert data
    gudb_exec(txn, "USE company", NULL, &result);
    if (result) gudb_free_result(result);
    gudb_exec(txn, "INSERT INTO employees VALUES (1, 'Bob', 50000.0)", NULL, &result);
    if (result) gudb_free_result(result);
    printf("Switched to company and inserted data into employees\n");
    
    // Verify data isolation by querying
    printf("Querying employees table:\n");
    if (gudb_exec(txn, "SELECT * FROM employees", NULL, &result) == GU_OK) {
        for (uint32_t i = 0; i < result->row_count; i++) {
            printf("  Employee: %s %s %s\n", result->rows[i][0], result->rows[i][1], result->rows[i][2]);
        }
        if (result->row_count == 0) {
            printf("  (no data)\n");
        }
        gudb_free_result(result);
    }
    
    print_separator("Final Result");
    printf("Database isolation test completed successfully!\n");
    printf("✅ Tables are properly isolated between databases\n");
    printf("✅ Cross-database access is properly blocked\n");
    printf("✅ Data insertion and querying works correctly\n");
    
cleanup:
    gudb_commit(txn);
    gudb_close(db);
    
    // Clean up
    system("rm -rf ./final_test_db");
    
    return 0;
}